/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.google.code.twiddling.core.io;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.StringTokenizer;
/**
 * This class acts as a buffer for user inputs
 * 
 * @author <a href="mailto:howard.gao@gmail.com">Howard Gao</a> 
 *
 */
public class InputBuffer {

	private LinkedList<Character> charBuffer = new LinkedList<Character>();
	private Character cr;
	private boolean alert = false;

	public InputBuffer() {
		String rechr = System.getProperty("line.separator");
		cr = new Character(rechr.charAt(0));
	}
	
	public void reset() {
		charBuffer.clear();
	}

	public synchronized boolean isAlert() {
		return alert;
	}
	
	private void checkAlert() {
		String inputQueue = dumpBuffer();
		StringTokenizer tokenizer = new StringTokenizer(inputQueue);
		while (tokenizer.hasMoreTokens()) {
			String t = tokenizer.nextToken();
			if ("exit".equals(t.trim()) || "bye".equals(t.trim())) {
				alert = true;
			} else {
				alert = false;
			}
		}
	}
	/**
	 * called by the input thread.
	 * @param c
	 */
	public synchronized void newInputChar(Character c) {
		charBuffer.add(c);
		if (cr.equals(c)) {
			checkAlert();
		}
		notify();
	}
	
	private String dumpBuffer() {
		StringBuffer sb = new StringBuffer();
		Iterator<Character> ibuf = charBuffer.iterator();
		while (ibuf.hasNext()) {
			sb.append(ibuf.next().charValue());
		}
		return sb.toString();
	}

	public synchronized String getCommandString() {
		StringBuffer sb = new StringBuffer();
		while (true) {
			if (charBuffer.isEmpty()) {
				try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			} else {
				Character ch = charBuffer.removeFirst();
				if (ch.equals(cr)) {
					break;
				} else {
					sb.append(ch.charValue());
				}
			}
		}
		return sb.toString().trim();
	}

	public synchronized String getCommandString(long timeout) {
		if ( !charBuffer.contains(cr)) {
			try {
				wait(timeout);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			if (!charBuffer.contains(cr)) {
				return null;
			}
		}
		StringBuffer sb = new StringBuffer();
		while (true) {
			Character ch = charBuffer.removeFirst();
			if (ch.equals(cr)) {
				break;
			} else {
				sb.append(ch.charValue());
			}
		}
		return sb.toString();
	}
	
}
